#ifndef xpack_instruction_count_of_set
#define xpack_instruction_count_of_set
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::instruction_count_of_set::inc
#include"configure/platform.hpp"
#include"define/base_type.hpp"
#include"macro/xexport.hpp"
#include"memop/cast.hpp"
#include"meta/is_number.hpp"
#include"meta/unsigned_type.hpp"
#pragma pop_macro("xuser")

/*
陷阱：
u08 mask;
...

// 错误用法：
// 这里 mask 是 u08，~mask 之后会隐式转换成 int 类型，导致高 3 个字节所有的位都变成全 1 的情况
// 无论是 u08 还是 i08、u16、i16 都会有这种问题，只有位宽不小于 int 的整数类型才不会有此问题
inc::count_of_set(~mask);

// 正确用法：
// count_of_reset 做了类型匹配
inc::count_of_reset(mask);
*/

namespace mixc::instruction_count_of_set{
    template<inc::is_number number_t>
    inline uxx count_of_set(number_t v){
        // 避免有符号数的符号位扩展
        using u_t   = inc::unsigned_type<number_t>;
        u_t uv      = inc::cast<u_t>(v);

        #if xis_msvc_native
            #if xis_os64
                return __popcnt64(uv);
            #elif xis_os32
                if constexpr (sizeof(uv) == 8){
                    return uxx(__popcnt(uv & u32(-1)) + __popcnt(uv >> 32));
                }
                else {
                    return __popcnt(uv);
                }
            #endif
        #else
            #if xis_os64
                return __builtin_popcountll(uv);
            #elif xis_os32
                if constexpr (sizeof(uv) == 8){
                    return __builtin_popcount(uv & u32(-1)) + __builtin_popcount(u64(uv) >> 32);
                }
                else {
                    return __builtin_popcount(uv);
                }
            #endif
        #endif

    }
}

#endif

xexport(mixc::instruction_count_of_set::count_of_set)